<?php
declare (strict_types=1);

namespace app\admin\controller;

use app\BaseController;
use app\common\tool\Result;
use think\helper\Str;
use think\Response;

class Uploads extends BaseController
{
    //错误信息
    public string $error;

    //允许上传格式
    protected string $fileExt = 'jpg,png,gif,jpeg';

    //上传大小限制
    protected string $filesize = '10485760';

    protected string $regular = "/(3c25.*?28.*?29.*?253e)|(3c3f.*?28.*?29.*?3f3e)|(3C534352495054)|(2F5343524950543E)|(3C736372697074)|(2F7363726970743E)/is";

    public function uploadImage(): Response
    {
        $file = request()->file();
        try {
            $this->validate($file, ['file' => 'filesize:' . $this->filesize . '|fileExt:' . $this->fileExt . '']);
            $url = '/uploads/admin/image/' . date('Ymd');
            $path = app()->getRootPath() . 'public/uploads/admin/image/' . date('Ymd');
            $name = md5(time() . Str::random(32)) . '.' . $file['file']->getOriginalExtension();
            $result = $file['file']->move($path, $name);
            $image = $url . '/' . $result->getFileName();
            if (!$this->illegalCheck($image)) {
                throw new \Exception($this->error);
            }

        } catch (\Exception $e) {

            return Result::fail('上传失败:' . $e->getMessage());
        }

        return Result::success('上传成功', ['url' => $image, 'name' => $result->getFileName()]);
    }

    public function uploadVideo(): Response
    {
        $file = request()->file();
        try {
            $this->validate($file, ['file' => 'filesize:52428800|fileExt:mp4']);
            $url = '/uploads/admin/video/' . date('Ymd');
            $path = app()->getRootPath() . 'public/uploads/admin/video/' . date('Ymd');
            $name = md5(time() . Str::random(32)) . '.' . $file['file']->getOriginalExtension();
            $result = $file['file']->move($path, $name);
            $video = $url . '/' . $result->getFileName();

        } catch (\Exception $e) {

            return Result::fail('上传失败:' . $e->getMessage());
        }

        return Result::success('上传成功', ['url' => $video, 'name' => $result->getFileName()]);
    }

    public function uploadEditorVideo(): Response
    {
        $file = request()->file();
        try {
            $this->validate($file, ['file' => 'filesize:52428800|fileExt:mp4']);
            $url = '/uploads/admin/video/' . date('Ymd');
            $path = app()->getRootPath() . 'public/uploads/admin/video/' . date('Ymd');
            $name = md5(time() . Str::random(32)) . '.' . $file['wangeditor-uploaded-video']->getOriginalExtension();
            $result = $file['wangeditor-uploaded-video']->move($path, $name);
            $image = $url . '/' . $result->getFileName();

        } catch (\Exception $e) {

            return Result::fastReturn(['errno' => 1, 'message' => '上传失败:' . $e->getMessage()]);
        }

        return Result::fastReturn(['errno' => 0, 'data' => ['url' => $image, 'alt' => $file['wangeditor-uploaded-video']->getOriginalName()]]);
    }

    public function uploadFile(): Response
    {
        $file = request()->file();
        try {
            $this->validate($file, ['file' => 'filesize:' . $this->filesize . '|fileExt:xls,xlsx']);
            $url = '/uploads/admin/file/' . date('Ymd');
            $path = app()->getRootPath() . 'public/uploads/admin/file/' . date('Ymd');
            $name = md5(time() . Str::random(32)) . '.' . $file['file']->getOriginalExtension();
            $result = $file['file']->move($path, $name);
            $file = $url . '/' . $result->getFileName();

        } catch (\Exception $e) {

            return Result::fail('上传失败:' . $e->getMessage());
        }

        return Result::success('上传成功', ['url' => $file, 'name' => $result->getFileName()]);
    }

    private function illegalCheck($disks): bool
    {
        $file = '.' . $disks;
        if (file_exists($file)) {
            $resource = fopen($file, 'rb');
            $fileSize = filesize($file);
            fseek($resource, 0);
            if ($fileSize > 512) {
                $hexCode = bin2hex(fread($resource, 512));
                fseek($resource, $fileSize - 512);
                $hexCode .= bin2hex(fread($resource, 512));
            } else { // 取全部
                $hexCode = bin2hex(fread($resource, $fileSize));
            }
            fclose($resource);

            $check = preg_match('#__HALT_COMPILER()#i', $hexCode)
                || preg_match('#/script>#i', $hexCode)
                || preg_match('#<([^?]*)\?php#i', $hexCode)
                || preg_match('#<\?\=#i', $hexCode);
            if ($check) {
                $this->error = '非法文件上传！';
                $this->remove($file);
                return false;
            }

            $result = preg_match($this->regular, $hexCode);

            if ($result) {
                $this->error = '非法文件上传！';
                $this->remove($file);
                return false;
            } else {
                return true;
            }
        } else {
            return false;
        }
    }

    private function remove($file): bool
    {
        if (file_exists($file)) {
            unlink($file);
            return true;
        } else {
            return false;
        }
    }
}